/**
 * Copyright (c) 2010
 * Bert Young. UESTC. 
 */

#include <strings.h>
#include "MsgBuffer.h"

void MsgBuffer::finalClear()
{
	bool isArrayFull = false;
	while ( (isArrayFull = moveToArray()) )
	{
		while ( get() != NULL )
			erase();
	}

	while ( get() != NULL )
		erase();
}

MsgBuffer::MsgBuffer() : readPtr(0), writePtr(0)
{
}

MsgBuffer::~MsgBuffer()
{
	this->finalClear();
}

CMD * MsgBuffer::get()
{
	CMD * ret = NULL;
	if ( READABLE == msgArray[readPtr].first )
	{
		ret = &msgArray[readPtr].second;
	}
	return ret;
}

void MsgBuffer::erase()
{
	delete msgArray[readPtr].second.second;
	msgArray[readPtr].first = WRITABLE;
	readPtr = (++readPtr) % ARRAYSIZE;
}

bool MsgBuffer::moveToArray()
{
	bool isArrayFull = false;
	while ( !dumpQueue.empty() )
	{
		if ( WRITABLE == msgArray[writePtr].first )
		{	
			msgArray[writePtr].first = READABLE;
			msgArray[writePtr].second = dumpQueue.front();
			writePtr = (++writePtr) % ARRAYSIZE;
			dumpQueue.pop();
		}
		else
		{
			isArrayFull = true;
			break;
		}
	}
	return isArrayFull;
}

bool MsgBuffer::put(const void * cmd, unsigned int len)
{
	unsigned char * buf = new unsigned char[len]();
	if ( buf )
	{
		bcopy( cmd, buf, len );
		if ( !moveToArray() && WRITABLE == msgArray[writePtr].first )
		{
			msgArray[writePtr].second.second = buf;
			msgArray[writePtr].second.first = len;
			msgArray[writePtr].first = READABLE;
			writePtr = (++writePtr) % ARRAYSIZE;
		}
		else
		{
			dumpQueue.push( std::make_pair(len, buf) );
		}
		return true;
	}
	return false;
}

void MsgBuffer::doCmd()
{
	CMD * cmd = this->get();
	while ( cmd != NULL )
	{
		this->msgParse(cmd->second, cmd->first);
		this->erase();
		cmd = this->get();
	}
}


